package com.lagou.edu.servlet;

import com.komodo.community.utils.YamlUtil;
import com.lagou.edu.context.ApplicationContext;
import com.lagou.edu.pojo.Result;
import com.lagou.edu.service.TransferService;
import com.lagou.edu.utils.JsonUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

/**
 * @author 应癫
 */
@WebServlet(name = "transferServlet", urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {

    private ApplicationContext applicationContext;

    private TransferService transferService;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("UTF-8");
        String fromCardNo = req.getParameter("fromCardNo");
        String toCardNo = req.getParameter("toCardNo");
        String moneyStr = req.getParameter("money");
        int money = Integer.parseInt(moneyStr);
        Result result = new Result();
        try {
            transferService = (TransferService) applicationContext
                    .getBean("TransferService", applicationContext);
            transferService.transfer(fromCardNo, toCardNo, money);
            result.setStatus("200");
        } catch (Exception e) {
            e.printStackTrace();
            result.setStatus("201");
            result.setMessage(e.toString());
        }
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().print(JsonUtils.object2Json(result));
    }

    /**
     * 修改内容：
     * 1.移除BeanFactory.java和beans.xml，采用包扫描整个目录下的所有bean，包路径配置在application.yml中，init()中读取
     * 2.ApplicationContext类构造器初始化了所有的bean，初始化在容器iocContainer中
     * 3.定义servlet容器init()方法，容器启动时初始化ApplicationContext
     * 4.ApplicationContext构造器读取application.yml配置的包路径下所有的bean，并实例化所有bean，存储到iocContainer中
     * 5.servlet的doPost方法中使用applicationContext.getBean()获取对象的bean处理业务逻辑
     * 6.使用反射获取bean对象的所有Field，injectContainer()(递归)方法首先判断是否有@Autowired注解，对注入的bean进行实例化操作
     * 7.判断是否有@Transactional注解，之后获取ProxyFactory bean，走定义好的jdk动态处理，处理事务回滚操作，并且返回代理对象，因此执行业务操作就可以走代理类的匿名内部类方法
     * 8.@Autowired目标是方法或字段等，@Service和Transactional目标是类，调用addClass()加载完所有的类以后，注入IOC容器时，会获取@Service注解，拿到注解的value值，使用这个值作为bean name存储到IOC容器中，否则使用类名
     */
    @Override
    public void init() {
        try {
            this.applicationContext = new ApplicationContext(
                    YamlUtil.readYaml("application.yml", "base.package", String.class));
        } catch (IOException | ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}
